import { roleApi, menuApi } from "@/api";
import { cloneDeep } from "@/utils";
import { NSpace, TreeOption } from "naive-ui";
import { Icon } from "@iconify/vue";

interface TreeOptionMeta {
  menu: Menu;
  parent?: TreeOption;
}

export const useGetMenuTree = (treeLoading: Ref<number>) => {
  const menuTree = ref<TreeOption[]>([]);
  const allTreeKeys = ref<string[]>([]);

  const getMenuTree = async () => {
    treeLoading.value++;
    try {
      const { status, data } = await menuApi.getTree();
      if (status) {
        menuTree.value = menu2TreeOption(data);
      }
    } finally {
      treeLoading.value--;
    }
  };

  const menuItemColorMapping = { 0: "#2080f0", 1: "#f0a020", 2: "#18a058" };
  const menu2TreeOption = (
    menus?: Menu[],
    parent?: TreeOption
  ): TreeOption[] => {
    if (!menus) return [];
    return menus.map((menu) => {
      const isLeaf = !menu.children || !menu.children.length;
      if (!isLeaf) allTreeKeys.value.push(menu.id!);

      const treeOption: TreeOption = {
        key: menu.id,
        label: "",
        isLeaf,
        meta: { menu, parent } as TreeOptionMeta,
        prefix: () => (
          <NSpace justify="center" align="center">
            {menu.icon ? (
              <Icon class="ml-5 text-16" icon={menu.icon} />
            ) : undefined}
            <div mx-5 style={{ color: menuItemColorMapping[menu.type!] }}>
              {menu.name}
            </div>
          </NSpace>
        ),
      };
      treeOption.children = menu2TreeOption(menu.children, treeOption);
      return treeOption;
    });
  };

  return { treeLoading, menuTree, allTreeKeys, getMenuTree };
};

export const useGetRolePerms = (
  props: { role?: Role },
  treeLoading: Ref<number>
) => {
  watch(
    () => props.role,
    async (newV) => {
      if (newV?.id) getUserPerms(newV.id);
    }
  );

  const expandedKeys = ref<string[]>([]);
  const checkedKeys = ref<string[]>([]);
  const checkedKeysTemp = ref<string[]>([]);

  const getUserPerms = async (userId: string) => {
    treeLoading.value++;
    try {
      const { status, data } = await roleApi.getPermsById(userId);
      if (status) {
        checkedKeys.value = data;
        expandedKeys.value = data;
        checkedKeysTemp.value = cloneDeep(data);
      }
    } finally {
      treeLoading.value--;
    }
  };
  return { expandedKeys, checkedKeys, checkedKeysTemp, getUserPerms };
};

export const useCheckUpdate = (checkedKeys: Ref<string[]>) => {
  const onCheckedUpdate = (
    _keys: Array<string | number>,
    _option: Array<TreeOption | null>,
    meta: { node: TreeOption | null; action: "check" | "uncheck" }
  ) => {
    if (meta.action === "check") {
      // 直系父节点一同选择
      cascadeCheck(meta.node);
    } else {
      // 直系子节点一同取消
      cascadeUnCheck(meta.node);
    }
  };

  const cascadeCheck = (node?: TreeOption | null) => {
    if (!node) return;
    const menuKey = node.key as string;
    if (!checkedKeys.value.includes(menuKey)) {
      checkedKeys.value.push(menuKey);
    }
    const nodeMeta = node.meta as TreeOptionMeta;
    cascadeCheck(nodeMeta.parent);
  };
  const cascadeUnCheck = (node?: TreeOption | null) => {
    if (!node) return;
    const menuKey = node.key as string;
    checkedKeys.value = checkedKeys.value.filter((key) => key !== menuKey);

    if (!node.children) return;
    for (const child of node.children) {
      cascadeUnCheck(child);
    }
  };
  return { onCheckedUpdate };
};
